import { useState, useOptimistic, useTransition } from 'react';
function todoReducer(state, action) {
    switch (action.type) {
        case 'add':
            return [...state, action.todo];
        case 'delete':
            return state.filter(todo => todo.id !== action.id);
        default:
            return state;
    }
}
function TodoApp() {
    //使用useState定义待办事项的列表的状态
    const [todos, setTodos] = useState([
        { id: crypto.randomUUID(), text: '学习React19' },
        { id: crypto.randomUUID(), text: '学习useOptimistic' }
    ]);
    //使用useOptimistic实现乐观更新
    const [optimisticTodos, addOptimisticTodo] = useOptimistic(todos, todoReducer);
    //使用useTransition处理异步状态更新
    const [isPending, startTransition] = useTransition();
    const handleAdd = async (formData) => {
        const text = formData.get('todo').trim();
        if (!text) return;
        //生成临时的ID
        const optimisticId = crypto.randomUUID();
        //创建临时待办事项对象
        const optimisticTodo = {
            id: optimisticId,
            text
        }
        //使用startTransition包装异步操作，异步操作一般是一个async函数
        //首先等async函数执行完了以后，如果真实状态todos并没有更新，那么
        startTransition(async () => {
            //通过派发动作实现乐观更新
            addOptimisticTodo({ type: 'add', todo: optimisticTodo });
            try {
                //模拟一个服务端的异步调用,服务器端会返回真实的ID
                const serverGeneratedId = await new Promise((resolve) => setTimeout(() => resolve(crypto.randomUUID()), 2000));
                //创建真实的待办事项
                const actualTodo = {
                    id: serverGeneratedId,
                    text
                }
                //更新实际状态
                setTodos((prevState) => [...prevState, actualTodo]);
            } catch (error) {
                console.log('添加TODO失败', error);
            }
        });
    }
    const handleDelete = async (id) => {
        startTransition(async () => {
            //通过派发动作实现乐观更新
            addOptimisticTodo({ type: 'delete', id });
            try {
                //模拟一个服务端的异步调用,服务器端会返回真实的ID
                await new Promise((resolve) => setTimeout(resolve, 2000));
                //更新实际状态
                setTodos((prevState) => prevState.filter(todo => todo.id !== id));
            } catch (error) {
                console.log('添加TODO失败', error);
            }
        });
    }
    return (
        <div>
            <h1>待办事项</h1>
            <form>
                <input type='text' name='todo' placeholder='输入新的待办事项' disabled={isPending} />
                <button formAction={handleAdd} disabled={isPending}>
                    {isPending ? '...' : '添加'}
                </button>
            </form>
            <ul>
                {
                    optimisticTodos.map(todo => (
                        <li key={todo.id}>
                            {todo.text}
                            <button onClick={() => handleDelete(todo.id)} disabled={isPending}>删除</button>
                        </li>
                    ))
                }
            </ul>
        </div>
    )

}
export default TodoApp;
/**
Encountered two children with the same key, `0651a893-5c6e-4a97-89c9-d4f423598aaa`. 
Keys should be unique so that components maintain their identity across updates.
 */